import { Compiler, Component, ComponentRef, Injector, ViewChild, ViewContainerRef, EventEmitter, Output } from '@angular/core';
import { appModuleAnimation } from '@shared/animations/routerTransition';
import { AddOrUpdateReplyInput, ExecuteActionInput, FormDataOutput, GetNodeListType, GoBackInput, UpdateFormDataInput, WorkFlowActionDto, WorkFlowServiceProxy } from '@shared/service-proxies/service-proxies';
import { finalize } from 'rxjs/operators';
import { ModalDirective } from 'ngx-bootstrap/modal';
import { DateTime } from 'luxon';
import { WorkFlowHelper } from '@app/shared/common/workflow/workflow-helper.service';
import { IBackWorkFlowListData, IFlowDetailParam, IRemarkDataItem, ITranslateItem } from '@app/shared/common/workflow/workflow-common-interface';
import { HtmlHelper } from '@shared/helpers/HtmlHelper';
import {createWfFormComponentFactory} from './workflow-detal-form-factory'
import { AppModalComponentBase } from '@shared/common/app-modal-component-base';
import { AppBsModalService } from '@shared/common/appBsModal/app-bs-modal.service';
import { BackSelectionModelComponent } from './back-selection-modal.component';
import { UserSelectionModelComponent } from './user-selection-modal.component';

 enum ActionType{
    goBack = 0,
    goNext = 1,
    current = 2
 }

@Component({
    selector:'workFlowDetail',
    templateUrl: './workflow-detail.component.html',
    animations: [appModuleAnimation()],
    styleUrls: ['./workflow-detail.component.css']
})
export class WorkflowDetailComponent extends AppModalComponentBase {
    @ViewChild('detailModal', { static: true}) modal: ModalDirective;
    @ViewChild('vc', {read: ViewContainerRef}) vc: ViewContainerRef;

    @Output() backListEvent: EventEmitter<IBackWorkFlowListData> = new EventEmitter<IBackWorkFlowListData>();
    private cmpRef: ComponentRef<any>;
    
    paperId:string;
    fieldDisabledData:{[key:string]:boolean};
    formData:{ [key: string]: any; };
    workFlowData: FormDataOutput = new FormDataOutput();
    replyMsg:string;
    remarkData: IRemarkDataItem[] = [];
    passRoundData: ITranslateItem[] = [];
    saving:boolean = false;

    btnEnabled = false;
    isLoading = false;

    actionType:ActionType;

    hadSavedData = false;

    isLoadingModal = false;

    constructor(
        public injector: Injector,
        private _workFlowServiceProxy:WorkFlowServiceProxy,
        private _workFlowHelper:WorkFlowHelper,
        private compiler: Compiler,
        private _modalService: AppBsModalService
    ) {
        super(injector);
    }


    show(moduleParams: IFlowDetailParam): void {
        this.ngOnDestroy();
        this.modalExpandOb.resetStates();
        this.hadSavedData = false;
        this.resertInitData();
        this.paperId = moduleParams.paperId;
        this.getWorkFlowData();
    }


    getWorkFlowData(){
        if (this.isLoadingModal) return;
        this.isLoadingModal = true;
        this.modal.show();
        this.isLoading = true;
        this._workFlowServiceProxy.getFormDataForEdit(this.paperId).pipe(finalize(()=>{
            this.isLoading = false;
            this.isLoadingModal = false;
        })).subscribe(result=>{
            this.workFlowData = result;
            this.workFlowData.formHtml = HtmlHelper.htmlDecode(result.formHtml);
            this.formData = result.formData.data;
            this.fieldDisabledData = result.formData.fieldDisabled;
            this.remarkData = this._workFlowHelper.getRemarkData(this.workFlowData.remarkData,this.workFlowData.additionalMsg)
            this.passRoundData = this._workFlowHelper.getPassRoundData(this.workFlowData.remarkData);
            this.replyMsg = result.replyMsg;
            
            this.createComponent(this.vc);
        })
    }

    workflowSave(action?:{():void}){
        if (!this.paperId || !this.workFlowData.paper.title){
            return;
        }
        if (this.workFlowData.actionState == 1) {
            const saveDataFunc = (otherCall:{():void})=> {
                if (this.workFlowData.canSave) {
                    this.isLoading = true;
                    this.beforeSave();

                    let submitData = new UpdateFormDataInput();
                    submitData.id = this.paperId;
                    submitData.paper = this.workFlowData.paper;
                    submitData.values = this.formData;
                    
                    this._workFlowServiceProxy.updateFormData(submitData).pipe(finalize(()=>{this.isLoading = false}))
                    .subscribe(result=>{
                        if (!action) {
                            this.notify.success(this.l('SavedSuccessfully'));
                        }
                        else {
                            action();
                        }
                    })
                } else {
                    otherCall();
                }
            };

            this.isLoading = true;

            let replyData = new AddOrUpdateReplyInput();
            replyData.paperId = this.paperId;
            replyData.replyMsg = this.replyMsg;
            replyData.hasRead = this.workFlowData.currentTask.hasRead;
            replyData.customData = this.workFlowData.currentTask.customData;

            this._workFlowServiceProxy.addOrUpdateReply(replyData).pipe(finalize(()=>{this.isLoading = false}))
            .subscribe(()=>{
                this.hadSavedData = true;
                saveDataFunc(()=> {
                    if (!action) {
                        this.notify.success(this.l('SavedSuccessfully'));
                    } else {
                        action();
                    }
                });
            });
        }
    }

    close(): void {
        this.modal.hide();
        if (this.hadSavedData){
            this.backListEvent.emit({isReload:true});
        }
    }

    excuteAction(item: WorkFlowActionDto):void{
        if (this.btnEnabled) {
            this.notify.warn(this.l('CurrentExcuting'));
            return;
        }
        if (item.needReply) {
            var errMsg = this.checkMsg(this.replyMsg);
            if (errMsg) {
                this.notify.warn(errMsg);
                return;
            }
        }

        const excustFunc =  (hasConfirm:boolean, needSelectUsers:boolean, isRequired:boolean, modalTitle?:string) => {
            
            const openSelectUsersModal =  () => {
                const bsModalRef = this._modalService.show(UserSelectionModelComponent, {
                    backdrop: 'static', class: 'modal-xl'
                });

                let getNodeType = GetNodeListType.Current;
                if (item.name === "提交") {
                    getNodeType = GetNodeListType.GoNext;
                }
        
                bsModalRef.content.shown({
                    paperId: this.paperId,
                    type: getNodeType,
                    nodeId: this.workFlowData.paper.nodeId,
                    actionName: item.name,
                    isRequired: isRequired,
                    modalTitle: modalTitle
                });
                bsModalRef.content.callback = (result) => {
                    if (result) {
                        this.isLoading = true;
                        if (this.btnEnabled) {
                            this.notify.warn(this.l('CurrentExcuting'));
                            return;
                        }
                        this.btnEnabled = true;
                        this._workFlowServiceProxy.executeAction(new ExecuteActionInput({
                            paperId: this.paperId,
                            actionName: item.name,
                            nodeId: result.selectNodeId,
                            userIdList: result.selectUserIdList,
                            actionScheme: result.selectActionScheme,
                            replyMsg: this.replyMsg,
                            turnRoundUserList: undefined
                        })).pipe(finalize(()=>{
                            this.isLoading = false;
                            this.btnEnabled = false;
                        })).subscribe(result => {
                            if (item.jsOnSuccessActionName) {
                                this.jsActionDic[item.jsOnSuccessActionName]();
                            } else {
                                this.goBackList();
                            }
                            this.notify.success(this.l('ExecuteSuccessfully'));
                        });
                    }
                };
            };
            if (needSelectUsers) {
                openSelectUsersModal();
            }
            else {
                const excustFuncInternal = () => {
                    this.isLoading = true;
                    if (this.btnEnabled) {
                        this.notify.warn(this.l('CurrentExcuting'));
                        return;
                    }
                    this.btnEnabled = true;
                    let excuteData = new ExecuteActionInput();
                    excuteData.paperId = this.paperId;
                    excuteData.actionName = item.name;
                    excuteData.replyMsg = this.replyMsg;
                    this._workFlowServiceProxy.executeAction(excuteData)
                    .pipe(finalize(()=>{
                        this.isLoading = false;
                        this.btnEnabled = false;
                    })).subscribe(result=>{
                        if (item.jsOnSuccessActionName) {
                            this.jsActionDic[item.jsOnSuccessActionName]();
                        } else {
                            this.goBackList();
                        }
                        this.notify.success(this.l('ExecuteSuccessfully'));
                    });
                  
                };
                excustFuncInternal();
            }
        };

        const checkStateBeforeExcuteAction =  () => {
            if (item.needCheckState) {
                this.isLoading = true;

                let executeActionData = new ExecuteActionInput();
                executeActionData.paperId = this.paperId;
                executeActionData.actionName = item.name;
                this._workFlowServiceProxy.checkStateBeforeExecuteAction(executeActionData).pipe(finalize(()=>{this.isLoading = false}))
                .subscribe(result=>{
                    this.isLoading = true;

                    if (result.confirmMsg) {
                        abp.message.confirm(
                            result.confirmMsg,"",
                            isConfirmed => {
                                if (isConfirmed) {
                                    if (result.reSetDefaultValue) {
                                        excustFunc(true, result.isNeedToSelectUsers, result.isRequired, result.modalTitle);
                                    } else {
                                        excustFunc(true, item.needSelectUsers, true, item.displayName);
                                    }
                                }
                            }
                        );
                    } else {
                        if (result.reSetDefaultValue) {
                            excustFunc(false, result.isNeedToSelectUsers, result.isRequired, result.modalTitle);
                        } else {
                            excustFunc(false, item.needSelectUsers, true, item.displayName);
                        }
                    }
                });
             
            } else {
                excustFunc(false, item.needSelectUsers, true, item.displayName);
            }
        };

        if (item.jsActionName) {
            this.jsActionDic[item.jsActionName](item);
        } else {
            if (this.workFlowData.actionState == 1) {
                this.workflowSave(checkStateBeforeExcuteAction);
            } else {
                checkStateBeforeExcuteAction();
            }
        }
    }

  
    ngOnDestroy() {
        if(this.cmpRef) {
          this.cmpRef.destroy();
        }
    }

    /**
     * 自定义方法 字典
     */
    jsActionDic = {
        "piShiJianBH":()=>{

        }
    }

    downAttach(filePath:string){
        if (!filePath) return;
        window.open(filePath);
    }


    goBack(){
        if (this.btnEnabled) {
            this.notify.warn(this.l('CurrentExcuting'));
            return;
        }

        const gobackFunc =  (selectNodeId) => {
            this.isLoading = true;
            if (this.btnEnabled) {
                this.notify.warn(this.l('CurrentExcuting'));
                return;
            }
            this.btnEnabled = true;

            let goBackInput = new GoBackInput({
                paperId: this.paperId,
                nodeId : selectNodeId,
                replyMsg : this.replyMsg
            });
            this._workFlowServiceProxy.goBack(goBackInput).pipe(finalize(()=>{
                this.isLoading = false;
                this.btnEnabled = false;
            }))
            .subscribe(result=>{
                this.goBackList();
                this.notify.success(this.l('ExecuteSuccessfully'));
            });
        };

        let preNodeList = this.workFlowData.preNodeList;
        if (preNodeList.length === 1) {
            this.workflowSave(() => {
                gobackFunc(preNodeList[0]);
            });
        } else {
            this.workflowSave(() => {
                const bsModalRef = this._modalService.show(BackSelectionModelComponent, {
                    backdrop: 'static', class: 'modal-lg'
                });
        
                bsModalRef.content.shown(this.paperId, GetNodeListType.GoBack, this.workFlowData.paper.nodeId);
                bsModalRef.content.callback = (result) => {
                    if (result) {
                        gobackFunc(result.selectNodeId);
                    }
                };
            });
        }
    }

    goReplyMsgModel(){
        // TODO: 快捷回复
    }

      /**
     * 保存前
     */
    beforeSave(){

    }

    checkState(data: ITranslateItem){
        return this._workFlowHelper.checkState(data);
    }

    timeDiffCalc(state:number, markTime:DateTime, finishedTime:DateTime){
        return this._workFlowHelper.timeDiffCalc(state, markTime, finishedTime);
    }

    timeFormat(time:DateTime){
        return this._workFlowHelper.timeFormat(time);
    }

    checkMsg(txt:string) {
        if (this.workFlowData.paper.paperState === 0 || this.workFlowData.paper.creatorUserId === abp.session.userId) {
            return "";
        }

        if (this.workFlowData.currentTask.operationType === 0) {
            if (!this.workFlowData.currentTask.hasRead) {
                return "请勾选已阅！";
            }
        } else {
            txt = !txt ? '' : txt.trim();
            if (!txt) {
                if (!this.workFlowData.currentTask.customData) {
                    return "意见结果不能为空！";
                }
            } else if (txt === "已阅" || txt === "阅" || txt === "已阅。" || txt === "已阅.") {
                return "请在意见栏中填写具体办理意见，如：同意、已审核等。";
            }
        }
        return "";
    }


    goBackList(){
        this.modal.hide();
        this.backListEvent.emit({isReload:true});
    }
    
    protected createComponent(ref: ViewContainerRef) {
        let that = this;
        let tempFunc = function () {
            this.formData = that.formData;
            this.fieldDisabledData = that.fieldDisabledData;
            this.paperId = that.paperId;
        };
        createWfFormComponentFactory(this.compiler, this.workFlowData.formHtml, tempFunc).then(factory => {
          const injector = Injector.create({ providers: [], parent: ref.injector });
          const cmpRef = ref.createComponent(factory, 0, injector, []);

          cmpRef.instance.name = "dynamic-wf-component";
          this.cmpRef = cmpRef;
        });
      }

    private resertInitData():void{
        this.workFlowData = new FormDataOutput();
        this.fieldDisabledData = {};
        this.formData = {};
        this.replyMsg = "";
        this.remarkData = [];
        this.passRoundData = [];
    }
}





